package com.wjjun.base.utils

import androidx.databinding.ListChangeRegistry
import androidx.databinding.ObservableArrayList
import androidx.databinding.ObservableList
import androidx.databinding.ObservableList.OnListChangedCallback

/**
 * 比起ObservableArrayList多了move方法
 */
class ObArrayList<T> : ArrayList<T>(), ObservableList<T> {

    private val mListeners = ListChangeRegistry()

    override fun addOnListChangedCallback(callback: OnListChangedCallback<out ObservableList<T>>?) {
        this.mListeners.add(callback)
    }

    override fun removeOnListChangedCallback(callback: OnListChangedCallback<out ObservableList<T>>?) {
        this.mListeners.remove(callback)

    }

    override fun add(element: T): Boolean {
        super.add(element)
        this.notifyAdd(this.size - 1, 1)
        return true
    }

    override fun add(index: Int, element: T) {
        super.add(index, element)
        this.notifyAdd(index, 1)
    }

    override fun addAll(elements: Collection<T>): Boolean {
        val oldSize: Int = this.size
        val added: Boolean = super.addAll(elements)
        if (added) {
            this.notifyAdd(oldSize, this.size - oldSize)
        }
        return added
    }

    override fun addAll(index: Int, elements: Collection<T>): Boolean {
        val added: Boolean = super.addAll(index, elements)
        if (added) {
            this.notifyAdd(index, elements.size)
        }
        return added
    }

    override fun clear() {
        val oldSize: Int = this.size
        super.clear()
        if (oldSize != 0) {
            this.notifyRemove(0, oldSize)
        }
    }

    override fun remove(element: T): Boolean {
        val index: Int = this.indexOf(element)
        return if (index >= 0) {
            this.removeAt(index)
            true
        } else {
            false
        }
    }

    override fun removeAt(index: Int): T {
        val element = super.removeAt(index)
        notifyRemove(index, 1)
        return element
    }

    override fun set(index: Int, element: T): T {
        val e: T = super.set(index, element)
        this.mListeners.notifyChanged(this, index, 1)
        return e
    }

    fun move(from: Int, to:Int){
        super.add(to, super.removeAt(from))
        notifyMove(from,to,1)
    }

    fun moveNoneNotify(from: Int, to:Int){
        super.add(to, super.removeAt(from))
    }

    override fun removeRange(fromIndex: Int, toIndex: Int) {
        super.removeRange(fromIndex, toIndex)
        this.notifyRemove(fromIndex, toIndex - fromIndex)
    }

    private fun notifyAdd(start: Int, count: Int) {
        this.mListeners.notifyInserted(this, start, count)
    }

    private fun notifyRemove(start: Int, count: Int) {
        this.mListeners.notifyRemoved(this, start, count)
    }

    private fun notifyMove(from: Int, to: Int, count: Int) {
        this.mListeners.notifyMoved(this, from, to, count)
    }

}
